﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Framework.Core.Recorder;
using Framework.Core.Reflection;
using Xunit;

namespace Framework.Tests.Core.Recorder
{
    public class DependencyParametersTest
    {
        class ArgumentMock : IArgument
        {
            public ArgumentMock(string value)
            {
                Value = value;
            }

            public Type Type { get { return typeof(string); } }
            public object Value { get; private set; }
        }

        class MethodMock : IMethod
        {
            public string Assembly { get; private set; }
            public string Type { get; private set; }
            public string Name { get; private set; }
            public IEnumerable<IArgument> Arguments { get; private set; }

            public MethodMock(MemberInfo methodInfo, IEnumerable<IArgument> arguments)
            {
                Assembly = methodInfo.Module.Assembly.FullName;
                Type = methodInfo.DeclaringType.FullName;
                Name = methodInfo.Name;
                Arguments = arguments;
            }
        }
        
        private readonly DependencyParameters dependencyParameters;

        public DependencyParametersTest()
        {
            dependencyParameters = new DependencyParameters(new MethodMock(typeof(ITest).GetMethod("JustDoIt"),new List<IArgument> { new ArgumentMock("a") }));
        }

        [Fact]
        public void Test_GetEnumerator()
        {
            Assert.NotNull(dependencyParameters.GetEnumerator());
        }

        [Fact]
        public void Test_Add()
        {
            var dependencyParameter = new DependencyParameter(null, null);
            dependencyParameters.Add(dependencyParameter);
            Assert.Equal(dependencyParameter, dependencyParameters.Last());
        }

        [Fact]
        public void Test_Clear()
        {
            dependencyParameters.Clear();

            Assert.Empty(dependencyParameters);
        }

        [Fact]
        public void Test_Contains()
        {
            var dependencyParameter = new DependencyParameter(null, null);
            dependencyParameters.Add(dependencyParameter);

            Assert.True(dependencyParameters.Contains(dependencyParameter));
        }

        [Fact]
        public void Test_CopyTo()
        {
            var copy = dependencyParameters.ToArray();
            dependencyParameters.CopyTo(copy, 0);

            Assert.Equal(copy, dependencyParameters);
        }

        [Fact]
        public void Test_Remove()
        {
            var dependencyParameter = new DependencyParameter(null, null);
            dependencyParameters.Add(dependencyParameter);

            dependencyParameters.Remove(dependencyParameter);

            Assert.False(dependencyParameters.Contains(dependencyParameter));
        }

        [Fact]
        public void Test_Count()
        {
            Assert.Equal(1, dependencyParameters.Count);
        }

        [Fact]
        public void Test_IsReadOnly()
        {
            Assert.False(dependencyParameters.IsReadOnly);
        }

        [Fact]
        public void Test_IndexOf()
        {
            var dependencyParameter = new DependencyParameter(null, null);
            dependencyParameters.Add(dependencyParameter);

            Assert.Equal(dependencyParameters.Count - 1, dependencyParameters.IndexOf(dependencyParameter));
        }

        [Fact]
        public void Test_Insert()
        {
            var dependencyParameter = new DependencyParameter(null, null);
            dependencyParameters.Insert(0, dependencyParameter);

            Assert.Equal(0, dependencyParameters.IndexOf(dependencyParameter));
        }

        [Fact]
        public void Test_RemoveAt()
        {
            var dependencyParameter = new DependencyParameter(null, null);
            dependencyParameters[0] = dependencyParameter;

            dependencyParameters.RemoveAt(0);

            Assert.Empty(dependencyParameters);
        }

        internal interface ITest
        {
            string JustDoIt(string a);
        }
    }
}